package com.swyc.osschat.Test.LambdaTest.Controller;

import java.util.List;
import java.util.Objects;
import java.util.function.BiFunction;
import java.util.function.DoubleFunction;
import java.util.function.DoubleToIntFunction;
import java.util.function.Function;
import java.util.function.ToDoubleBiFunction;

import com.google.common.collect.ImmutableList;
import com.swyc.osschat.Test.LambdaTest.Bean.Student;
import com.swyc.osschat.Test.StreamTest.Bean.SpecialityEnum;

import net.sf.jsqlparser.expression.DoubleValue;

/**
 * @author zhaol@yunrong.cn
 * @version V2.1
 * @since 2.1.0 2019/8/12 20:19
 * BiFunction<T,U,R>
 * 接受两个参数并返回结果的函数
 * DoubleFunction<R>
 * 接收一个double类型的参数并返回结果的函数
 * DoubleToIntFunction
 * 接收一个double类型的参数并返回int结果的函数
 * DoubleToLongFunction
 * 接收一个double类型的参数并返回long结果的函数
 * IntFunction<R>
 * 接收一个int类型的参数并返回结果的函数
 * IntToDoubleFunction
 * 接收一个int类型的参数并返回double结果的函数
 * IntToLongFunction
 * 接收一个int类型的参数并返回long结果的函数
 * LongFunction<R>
 * 接收一个long类型的参数并返回结果的函数
 * LongToDoubleFunction
 * 接收一个long类型的参数并返回double结果的函数
 * LongToIntFunction
 * 接收一个long类型的参数并返回int结果的函数
 * ToDoubleBiFunction<T,U>
 * 接收两个参数并返回double结果的函数
 * ToDoubleFunction<T>
 * 接收一个参数并返回double结果的函数
 * ToIntBiFunction<T,U>
 * 接收两个参数并返回int结果的函数
 * ToIntFunction<T>
 * 接收一个参数并返回int结果的函数
 * ToLongBiFunction<T,U>
 * 接收两个参数并返回long结果的函数
 * ToLongFunction<T>
 * 接收一个参数并返回long结果的函数
 */
public class FunctionTest2 {
    public static void main(String[] args) {
        List<Student> students = Student.generateData();
        Function<Student,String> function = a -> Student.beanToString(a);
        System.out.println(function.apply(students.get(0)));
        Function<List<Student>,Student> functionAndthen = a -> a.get(a.size()-1);
        /** andThen 在functionAndthen这个函数执行之后再执行function */
        System.out.println(functionAndthen.andThen(function).apply(students));
        /** compose 在function这个函数执行之前执行functionAndthen*/
        System.out.println(function.compose(functionAndthen).apply(students));
        /** BiFunction<T,U,R>接受两个参数并返回结果的函数 */
        BiFunction<Student,Integer,Student> biFunction = (a,b)->Student.modifyStudentAge(a,b);
        BiFunction<List<Student>,Integer,Student> biFunction1 = (a,b)-> Objects.nonNull(a)?a.get(b):new Student(1,"老皇帝", 50, 185,
            ImmutableList.of(SpecialityEnum.SING,SpecialityEnum.DANCE,SpecialityEnum.RUNNING),"1",4);
        System.out.println(biFunction1.andThen(function).apply(null,5));
        /** DoubleFunction<R>接收一个double类型的参数并返回结果的函数 */
        DoubleFunction<Student> doubleFunction = a -> Student.modifyStudentAge(a);
        System.out.println(Student.beanToString(doubleFunction.apply(56.3)));
        /** DoubleToIntFunction接收一个double类型的参数并返回int结果的函数 */
        DoubleToIntFunction doubleToIntFunction = a -> Double.valueOf(a).intValue();
        int i = doubleToIntFunction.applyAsInt(1.2);
        /** ToDoubleBiFunction<T,U>接收两个参数并返回double结果的函数 */
        ToDoubleBiFunction<Student,Integer> toDoubleBiFunction = (a,b)-> Double.valueOf(a.getAge()+b).doubleValue();
        double v = toDoubleBiFunction.applyAsDouble(students.get(4), 100);
        System.out.println(getSum(1,2,(a,b)->a+b));
        System.out.println(getSum(1,2,(a,b)->a-b));
        System.out.println(getSum(1,2,(a,b)->a*b));
        System.out.println(getSum(2,2,(a,b)->a/b));
    }

    public static Integer getSum(Integer a, Integer b, BiFunction<Integer, Integer, Integer> biFunction) {
        return biFunction.apply(a, b);
    }
}
